#include "rclcpp/rclcpp.hpp"
#include <vector>
using namespace std::chrono_literals;

//注意事项 
//1.get_parameter返回值不再是一个Parameter对象而是一个value，且需要模板
//2.set_parameter参数不再是Parameter对象而是一个vector容器

class ParamClient:public rclcpp::Node
{
public:
    ParamClient():Node("client_param_node")
    {
       
        client_param_=std::make_shared<rclcpp::SyncParametersClient>
        (
            this,
            "server_param_node"
        );
        /*
            为什么靠节点关联？
            1.参数服务端启动后，底层封装了多个服务通信的服务端;
            2.每个服务端的话题，都是采用/服务端节点名称/xxx;
            3.参数客户端创建后，也会封装多个服务通信的客户端；
            4.这些客户端与服务端相呼吁，也要使用相同的话题，
            因此客户端创建时需要使用服务端节点名称
        */
    }
    void connect_server()
    {
        while(!client_param_->wait_for_service(1s))
        {
            if(!rclcpp::ok())
             {
                 exit(1);
             }
            RCLCPP_INFO(this->get_logger(),"服务连接中");
        }
    } 
    void get_param()
    {
        //这里不再返回键值对，只返回value值
        std::string car_name=client_param_->get_parameter<std::string>("car_name");
        double height=client_param_->get_parameter<double>("height");
        RCLCPP_INFO(this->get_logger(),"car_name=%s",car_name.c_str());
        RCLCPP_INFO(this->get_logger(),"height=%.2f",height);
        
        //这里还是返回键值的vector容器
        std::vector<rclcpp::Parameter> params=client_param_->get_parameters({"car_name","height","wheels"});
        for(auto param :params)
        {
            RCLCPP_INFO(this->get_logger(),"%s=%s",
            param.get_name().c_str(),
            param.value_to_string().c_str());
        }
        RCLCPP_INFO(this->get_logger(),"参数是否包含car_name?%d",client_param_->has_parameter("car_name"));
        RCLCPP_INFO(this->get_logger(),"参数是否包含car?%d",client_param_->has_parameter("car"));
    }
    void update_param()
    {
        //这里参数必须是一个vector容器
        client_param_->set_parameters({rclcpp::Parameter("car_name","pig")});

        //也可以在客户端新增参数，前提是服务端参数为true
        client_param_->set_parameters({rclcpp::Parameter("width",1.5),
           rclcpp::Parameter("length",2.1)
        });
        RCLCPP_INFO(this->get_logger(),"新增参数width=%.1f",client_param_->get_parameter<double>("width"));
        RCLCPP_INFO(this->get_logger(),"新增参数length=%.1f",client_param_->get_parameter<double>("length"));
    } 
private:
        rclcpp::SyncParametersClient::SharedPtr client_param_ ;   
      
};
int main(int argc,const char*const argv[])
{
    rclcpp::init(argc,argv);
    auto node=std::make_shared<ParamClient>();
    node->connect_server();
    node->get_param();
    RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"+++++++++++++++");
    node->update_param();
    RCLCPP_INFO(rclcpp::get_logger("rclcpp"),"+++++++++++++++");
    node->get_param();
    rclcpp::shutdown();
    return 0;
}